package LeetDev.a3d;

import javax.microedition.khronos.opengles.GL10;

public class Mesh extends ImpObj {
	private static TransparencyContainer s_transparencyContainers[]=new TransparencyContainer[64];
	private static int s_numTransContainers=0;
	
	private int m_numTriangles;
	private Box m_box=new Box();
	private boolean m_containsAlpha;
	private int m_flags;
	private SubMesh m_subMeshes[];
	private int	m_alphaSubMeshes;
	
	public Mesh(FileInput fin, final String name, byte type, Material[] material_ref, GL10 gl) throws Exception
	{
		super(name,type);
		int i;
		m_containsAlpha=false;
		m_flags=fin.popInt();
		m_box.min.x=fin.popFloat();m_box.min.y=fin.popFloat();m_box.min.z=fin.popFloat();
		m_box.max.x=fin.popFloat();m_box.max.y=fin.popFloat();m_box.max.z=fin.popFloat();
		int numofsubmeshes;
		numofsubmeshes=fin.popInt();
		m_subMeshes=new SubMesh[numofsubmeshes];
		for(i=0;i<numofsubmeshes;i++)
		{
			SubMesh tmp=new SubMesh(fin,material_ref);
			m_subMeshes[i]=tmp;
			if(tmp.haveAlpha()) {m_containsAlpha=true;}
		}
		compile(gl);
	}

	public static void initTransparencyList()
	{
		for(int t=s_transparencyContainers.length;--t>=0;)
		{
			s_transparencyContainers[t]=new TransparencyContainer();
		}
	}
	
	public static void clearTransparencyList()
	{
		s_numTransContainers=0;
	}

	public static void eraseTransparencyList()
	{
		for(int t=s_numTransContainers;--t>=0;)
		{
			s_transparencyContainers[t]=null;
		}
		s_transparencyContainers=null;
		s_numTransContainers=0;
	}
	
	public static void drawTransparencyList(GL10 gl)
	{
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		if(s_numTransContainers>0)
		{
			gl.glDepthMask(false);
//			Arrays.sort(s_transparencyContainers,0,s_numTransContainers);
			for(int t=s_numTransContainers;--t>=0;)
			{
				s_transparencyContainers[t].draw(gl);
			}
			gl.glDepthMask(true);
		}
		clearTransparencyList();
	}

	public void compile(GL10 gl)
	{
		// decide which drawing function to use.
//		int numofsubmeshes=(int)m_subMeshes.size();
		m_alphaSubMeshes=m_subMeshes.length;
		if(m_containsAlpha)
		{
			int i,j;
			m_alphaSubMeshes=0;
			// sort submeshes so transparency materials are last in list
			for(i=0;i<m_subMeshes.length;++i)
			{
				if(m_subMeshes[i].haveAlpha())
				{
					m_alphaSubMeshes=i;
					for(j=i+1;j<m_subMeshes.length;++j)
					{
						if(!m_subMeshes[j].haveAlpha())
						{
							SubMesh tmp=m_subMeshes[i];
							m_subMeshes[i]=m_subMeshes[j];
							m_subMeshes[j]=tmp;
							m_alphaSubMeshes=i+1;
							break;
						}
					}
					if(j==m_subMeshes.length) {break;}
				}
			}
		}

		// compile the meshes, materials and textures.
		m_numTriangles=0;
		for(int t=0;t<m_subMeshes.length;++t)
		{
			m_numTriangles+=m_subMeshes[t].getTriangleNum();
		}
	}

	
	public void draw(final Matrix matrix,GL10 gl)
	{
		gl.glLoadMatrixf(matrix.m,0);
		if((m_flags&0x1)!=0)
		{
			gl.glEnable(GL10.GL_CULL_FACE);
		}
		else
		{
			gl.glDisable(GL10.GL_CULL_FACE);
		}
		// draw opaque first
		int t;
		for(t=0;t<m_alphaSubMeshes;t++)
		{
			m_subMeshes[t].draw(gl);
		}
		for(t=m_alphaSubMeshes;t<m_subMeshes.length;t++)
		{
			s_transparencyContainers[s_numTransContainers++].set(m_subMeshes[t],matrix,m_flags);
			if(s_numTransContainers==s_transparencyContainers.length)
			{
				// This is one of the very few places in the frame handling where memory is allocated and freed.
				// To avoid garbage collection as much as possible, we only make the transparency buffer grow when necessary, and we only shrink it when the EventHandler changes.
				// So the buffer will grow up to the size needed by the EventHandler, and stay that way.
				TransparencyContainer tmp[]=new TransparencyContainer[s_transparencyContainers.length+64];
				System.arraycopy(s_transparencyContainers, 0, tmp, 0, s_numTransContainers);
				s_transparencyContainers=tmp;				
				for(t=s_transparencyContainers.length;--t>=s_numTransContainers;)
				{
					s_transparencyContainers[t]=new TransparencyContainer();
				}
			}
		}
	}
}
